property LingoF
-- Note: All functions called by 'process' should be tail recursive and to consume a paramater, the parameter should be curried when calling the function.


-- Cons version just for ImmutableList.
-- Defined here as helper to avoid reference Lists Module.
-- It should be private.
on public_ConsAsFunction_2
on ConsAsFunction me ,e,lst
  return lst.cons(e)
end

on public_EmptyList_0
on EmptyList me
  return (script "scrLingoF_ImmutableList").new()
end



on public_SeqToList_2
on SeqToList me, fn,currentElem
  @ =  LingoF.Compose
  
  if LingoF.IsNothing[currentElem]  then return fn  [me.EmptyList]
  else return me.SeqToList [@[fn][me.ConsAsFunction[ currentElem[1]  ]]]
end

on public_ApplySeq_2
on ApplySeq me, prev,currentElem
  if LingoF.IsNothing[currentElem] then return prev
  else return me.ApplySeq [prev[ currentElem[1] ]]
end

on public_AnonymousLambda_2
on AnonymousLambda me, args, currentElem
  if LingoF.IsNothing[currentElem] then
    c = (script "scrArgToVarClosure").new(1 + args.count())
    c.pVarNames = args
    return c
  else
    args.Add(currentElem[1])
    return me.AnonymousLambda [args]
  end if
end

on public_JSFunction_2
on JsFunction me, jsFN,currentElem
  if LingoF.IsNothing[currentElem] then return (script "scrJsLambdaFunction").new(jsFN[1])
  return (script "scrJsLambdaFunction").new(jsFN[1],currentElem[1])
end

on public_FunctionPointer_4
on FunctionPointer me, hnd,inst,argscount,___
  return (script "scrLambdaFunction").new(hnd[1],inst[1],argscount[1])
end

on LingoExpressionsHelper a1,a2,a3
  argsText = ""
  lstArgs = []
  if listP(a1) then lstArgs = a1
  else
    if (a1 <> "") then
      idel = the itemdelimiter    
      if a1 contains ":" then --voidP(a2) then
        the itemdelimiter = ":"
        a3 = a2
        a2 = a1
        a1 = item 1 of a1
        a2 = "return "& char (a1.length+2) to (a2.length) of a2
      end if
      the itemdelimiter = ","
      repeat with i = 1 to a1.item.count()
        lstArgs.add(item i of a1)
      end repeat
      the itemdelimiter = idel
    end if
  end if
  
  lambdaText = ""
  if listP(a2) then
    repeat with s in a2
      lambdaText =   lambdaText & s & RETURN
    end repeat
  else lambdaText = a2
  
  context = a3
  if voidP(context) then context = []
  repeat with i = context.count() down to 1
    if ilk(context) = #propList then lstArgs.addAt(1,string(context.getPropAt(i)))
    else lstArgs.addAt(1,"_"&string(i))
  end repeat
  
  lambda = (script "scrLambda").CreateLingoExpression(lstArgs,lambdaText)
  repeat with p in context
    lambda = lambda[p]
  end repeat
  
  return lambda
end

on LingoExpression me,a1,a2,a3,a4
  if a2 = [] then return LingoExpressionsHelper(a1[1])
  if a3 = [] then return LingoExpressionsHelper(a1[1],a2[1])
  return LingoExpressionsHelper(a1[1],a2[1],a3[1])
end

--    ---- FN as Lingo expression ---
--    --> a1-> args:expression <string>
--    
--    ---- FN as Lingo sentences ----
--    --> a1-> args<string|list<string>>
--    --  ie 1   [ "x","y" ]
--    --  ie 2     "x,y"
--    
--    --> a2-> body<string|list<string>>
--    --  ie 1    "singleline lingo sentence" 
--    --  ie 2    "line 1 lingo sentence" &RETURN& "line 2 lingo sentence"
--    --  ie 3    ["line 1 lingo sentence","line 2 lingo sentence"] 

on public_fun_2
on fun me , LingoExpressionFN, currentElem
  if LingoF.IsNothing[currentElem] then return LingoF.Apply -- ??
  if symbolP(currentElem[1]) then return me.FunctionPointer [ currentElem ]
  if objectP(currentElem[1]) then
    if currentElem[1].ilk= #jobject then return me.JSFunction [ currentElem ]
    return me.AnonymousLambda  [[]] [ currentElem ]
  end if
  return LingoExpressionFN [ currentElem ]
end


-------------


on getLambda me,sym
  l = LingoF().getLambda(#Lingo,#operator,1,sym)
  if voidP(l) then return LingoF().getLambda(#Lingo,sym)
  return l
end

on public_shortcut_ApplyList_1
on firstElement me, currentElem
  if LingoF.IsNothing[currentElem] then return LingoF.Apply
  else return me.shortcut_ApplyList_secondElement [currentElem [1] ]
end

on public_shortcut_ApplyList_secondElement_2
on shortcut_ApplyList_secondElement me,prev,currentElem
  if symbolP(prev) then fn = me.getLambda(prev)
  else fn = prev
  if LingoF.IsNothing[currentElem] then return fn
  else 
    if [#List,#PropList,#Call].getOne(prev) then return me.SeqToList [fn] [currentElem]
    else return me.ApplySeq [fn] [currentElem]
  end if  
end

-----------
on public_shortcut_CreateList_1
on shortcut_CreateList me, currentElem 
  if LingoF.IsNothing[currentElem] then return me.EmptyList
  else  return me.SeqToList [LingoF.id][currentElem]
end